
import os
os.environ['DISABLE_ARGUMENTS_CHECKER'] = "Yes"

from rqalpha.apis import *

from funcat import *

# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
def init(context):
    context.s1 = context.config.mod.sys_analyser.benchmark
    subscribe(context.s1)
    #
    context.is_got_bars = False
    context.long_holds = {}
    context.short_holds = {}
    context.dkx = 0
    context.madkx = 0
    context.freq = context.config.base.frequency
    context.rdb = RQAlphaDataBackend(data_proxy=Environment.get_instance().data_proxy)
    # 日线
    context.long = False
    context.short = False
    context.last_date = None
    context.rdb_1d = RQAlphaDataBackend()

# 你选择的证券的数据更新将会触发此段逻辑，例如日或分钟历史数据切片或者是实时数据切片更新
def handle_bar(context, bar_dict):
    # 开始编写你的主要的算法逻辑
    # bar_dict[order_book_id] 可以拿到某个证券的bar信息
    # context.portfolio 可以拿到现在的投资组合状态信息
    # TODO: 开始编写你的算法吧！
    if not context.is_got_bars:
      bars = history_bars(context.s1, 20+1, '1d', adjust_type='none')
      if len(bars) < 21:
        return
      context.is_got_bars = True
    # 先判断日线多空
    curr_date = Environment.get_instance().data_proxy.get_future_trading_date(context.now)
    last_date = get_previous_trading_date(curr_date)
    if context.last_date != last_date:
      with funcat_execution_context(date=last_date,
                          order_book_id=context.s1,
                          data_backend=context.rdb_1d) as fec:
          dkx,madkx = DKX()
          # 用上个周期的多空线判断
          if dkx > madkx:
            # 有空仓，先平仓
            context.short = False
            # 计算箱体，向上突破就做多
            top,left,right,bottom = BOX(-1)
            if HIGH > top:
              context.long = True
          elif dkx < madkx:
            # 有多仓，先清仓
            context.long = False
            # 计算箱体，向下突破就做空
            bottom,left,right,top = BOX(1)
            if LOW < bottom:
              context.short = True
      # 每天进来一次
      context.last_date = last_date
    # 再判断分钟多空
    with funcat_execution_context(date=context.now,
                         order_book_id=context.s1,
                         data_backend=context.rdb, 
                         freq=context.freq) as fec:
        dkx,madkx = DKX()
        # 用上个周期的多空线判断
        if context.dkx > context.madkx:
          # 日线不做空
          if not context.short:
            # 有空仓，先平仓
            if context.s1 in context.short_holds:
              ret = order_to(context.s1, 0, price=OPEN.value)
              if ret and ret[0].status == ORDER_STATUS.FILLED:
                  del context.short_holds[context.s1]
              print("BUY_CLOSE", context.dkx, context.madkx, dkx, madkx, OPEN)
          # 日线做多
          if context.long:
            # 计算箱体，向上突破就做多
            top,left,right,bottom = BOX(-1)
            if HIGH > top and context.s1 not in context.long_holds:
              s1 = instruments(context.s1)
              price = top.value + s1.tick_size()
              target_lots = int(context.portfolio.total_value * 0.5 / price / s1.contract_multiplier / s1.margin_rate)
              ret = order_to(context.s1, target_lots, price=price)
              if ret and ret[0].filled_quantity > 0:
                context.long_holds[context.s1] = context.now
              print("BUY_OPEN", context.dkx, context.madkx, dkx, madkx, HIGH, top)
              pass
        elif context.dkx < context.madkx:
          # 日线不做多
          if not context.long:
            # 有多仓，先清仓
            if context.s1 in context.long_holds:
              ret = order_to(context.s1, 0, price=OPEN.value)
              if ret and ret[0].status == ORDER_STATUS.FILLED:
                  del context.long_holds[context.s1]
              print("SELL_CLOSE", context.dkx, context.madkx, dkx, madkx, OPEN)
          # 日线做空
          if context.short:
            # 计算箱体，向下突破就做空
            bottom,left,right,top = BOX(1)
            if LOW < bottom and context.s1 not in context.short_holds:
              s1 = instruments(context.s1)
              price = bottom.value - s1.tick_size()
              target_lots = int(context.portfolio.total_value * 0.5 / price / s1.contract_multiplier / s1.margin_rate)
              ret = order_to(context.s1, -target_lots, price=price)
              if ret and ret[0].filled_quantity > 0:
                  context.short_holds[context.s1] = context.now
              print("SELL_OPEN", context.dkx, context.madkx, dkx, madkx, LOW, bottom)
              pass
        # 保存上一个多空线
        context.dkx = dkx
        context.madkx = madkx
    # 持仓
    if len(context.long_holds) > 0:
      print("long:", context.long_holds)
    if len(context.short_holds) > 0:
      print("short:", context.short_holds)


__config__ = {
  "base": {
    "strategy_name": "dkx_future",
    "start_date": "2021-01-01",
    "end_date": "2021-08-15",
    "frequency": "1m",
    "accounts": {
        "future": 1000000
    }
  },
  "extra": {
    "log_level": "warning",
  },
  "mod": {
    "sys_accounts": {
      "enabled": True,
      "validate_stock_position": False
    },
    "sys_analyser": {
      "benchmark": "AG99",
      "enabled": True,
      "plot": True
    },
    "sys_simulation": {
      "enabled": True,
      "signal": True
    }
  }
}


if __name__ == '__main__':
    from rqalpha import run_func
    import json
    # import cProfile
    # pr = cProfile.Profile()
    # pr.enable()
    # 您可以指定您要传递的参数
    ret = run_func(init=init, handle_bar=handle_bar, config=__config__)
    print(ret)
    # pr.disable()
    # pr.print_stats('cumtime')